home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-06-18 | 28.4 KB | 889 lines | [TEXT/CWIE] |
- #include "Solution.h"
-
- #include "ProblemUtils.h"
- #include "myqsort.h"
-
- #include <stdio.h>
- #include <Files.h>
- #include <Errors.h>
-
- #define PRINT_MOVES 0
- #define PRINT_PIECES 0
- #define PRINT_BOARD 0
- #define PRINT_CORRECT_RESULTS 1
-
- #define kMaxPiecesRemaining 32
- #define kMaxMoves 1024
-
- static char gCol[] = "abcdefgh";
- static char gRow[] = "12345678";
- static char gColor[] = " WB";
- static char gRank[] = "-pNBRQK";
- #define kKingCol 4
- #define kQueenCol 3
-
-
- static OSErr SortPiecesCmp(void *p1, void *p2, short *result)
- {
- ChessPiece *piece1=(ChessPiece *)p1;
- ChessPiece *piece2=(ChessPiece *)p2;
- if (piece1->pieceLocation.row < piece2->pieceLocation.row)
- {*result = -1; return noErr;}
- else if (piece1->pieceLocation.row > piece2->pieceLocation.row)
- {*result = 1; return noErr;}
- if (piece1->pieceLocation.col < piece2->pieceLocation.col)
- {*result = -1; return noErr;}
- else if (piece1->pieceLocation.col > piece2->pieceLocation.col)
- {*result = 1; return noErr;}
- *result = 0; return noErr;
- }
-
- static OSErr SortMovesCmp(void *m1, void *m2, short *result)
- {
- ChessMove *move1=(ChessMove *)m1;
- ChessMove *move2=(ChessMove *)m2;
- if (move1->fromSquare.row < move2->fromSquare.row)
- {*result = -1; return noErr;}
- else if (move1->fromSquare.row > move2->fromSquare.row)
- {*result = 1; return noErr;}
- if (move1->fromSquare.col < move2->fromSquare.col)
- {*result = -1; return noErr;}
- else if (move1->fromSquare.col > move2->fromSquare.col)
- {*result = 1; return noErr;}
- if (move1->toSquare.row < move2->toSquare.row)
- {*result = -1; return noErr;}
- else if (move1->toSquare.row > move2->toSquare.row)
- {*result = 1; return noErr;}
- if (move1->toSquare.col < move2->toSquare.col)
- {*result = -1; return noErr;}
- else if (move1->toSquare.col > move2->toSquare.col)
- {*result = 1; return noErr;}
- if (move1->capture && !move2->capture)
- {*result = -1; return noErr;}
- else if (!move1->capture && move2->capture)
- {*result = 1; return noErr;}
- if (move1->capture && move2->capture) {
- if (move1->capturedSquare.row < move2->capturedSquare.row)
- {*result = -1; return noErr;}
- else if (move1->capturedSquare.row > move2->capturedSquare.row)
- {*result = 1; return noErr;}
- }
- *result = 0; return noErr;
- }
-
- static OSErr ReadUInt32FromHandle( Handle data, UInt32 *number )
- {
- OSErr err;
- char line[MAX_LINE_LEN];
- char *p;
-
- p = line;
- if ( ProblemReadLineFromHandle( data, line, MAX_LINE_LEN ) && ProblemGetUInt32( &p, number ) && *p == 0 ) {
- err = noErr;
- } else {
- err = -1;
- }
- return err;
- }
-
- static OSErr ReadChessMoveFromHandle( Handle data, char *side,
- char *fromCol, char *fromRow,char *move,
- char *toCol, char *toRow, char *captureCol, char *captureRow)
- {
- OSErr err;
- char line[MAX_LINE_LEN];
- char *p;
-
- p = line;
- if ( ProblemReadLineFromHandle( data, line, MAX_LINE_LEN ) && *p == 0 ) {
- err = noErr;
- } else {
- err = -1;
- }
- *side = line[0];
- *fromCol = line[2];
- *fromRow = line[3];
- *move = line[4];
- *toCol = line[5];
- *toRow = line[6];
- if (*move=='x') {
- *captureCol = line[8];
- *captureRow = line[9];
- } else {
- *captureCol = 0;
- *captureRow = 0;
- }
- return err;
- }
-
- static OSErr ReadMoves(Handle indata, UInt32 numMoves, ChessMove *moves)
- {
- OSErr err = noErr;
- for (int j=0; j<numMoves;j++) {
- char p,c1,r1,c2,r2,c3,r3,move;
- err = ReadChessMoveFromHandle (indata, &p, &c1, &r1, &move, &c2, &r2, &c3, &r3);
- if ((j&1)==0) {
- if (p!='W') DebugStr("\p expecting white move");
- } else {
- if (p!='B') DebugStr("\p expecting black move");
- }
- if (move=='x') {
- moves[j].capture = true;
- moves[j].capturedSquare.col = c3-gCol[0];
- moves[j].capturedSquare.row = r3-gRow[0];
- } else {
- moves[j].capture = false;
- moves[j].capturedSquare.col = 0;
- moves[j].capturedSquare.row = 0;
- }
- moves[j].fromSquare.col = c1-gCol[0];
- moves[j].fromSquare.row = r1-gRow[0];
- moves[j].toSquare.col = c2-gCol[0];
- moves[j].toSquare.row = r2-gRow[0];
- }
- return err;
- }
-
- typedef struct Piece {
- PieceColor color;
- PieceRank rank;
- } Piece;
-
- typedef struct Board {
- Piece sq[8][8];
- Square kingSq;
- ChessMove lastMove;
- Boolean pieceNeverMoved[8][8];
- } Board;
-
- static void InitBoard(Board *b)
- {
- int row,col;
- for (col=0; col<8; col++) {
- b->sq[0][col].color = b->sq[1][col].color = kWhite;
- b->sq[7][col].color = b->sq[6][col].color = kBlack;
- b->sq[2][col].color = b->sq[3][col].color = kEmpty;
- b->sq[4][col].color = b->sq[5][col].color = kEmpty;
- b->sq[1][col].rank = b->sq[6][col].rank = kPawn;
- b->sq[2][col].rank = b->sq[3][col].rank = kNone;
- b->sq[4][col].rank = b->sq[5][col].rank = kNone;
- }
- b->sq[0][0] .rank= b->sq[0][7].rank = b->sq[7][0].rank = b->sq[7][7].rank = kRook;
- b->sq[0][1].rank = b->sq[0][6].rank = b->sq[7][1].rank = b->sq[7][6].rank = kKnight;
- b->sq[0][2].rank = b->sq[0][5].rank = b->sq[7][2].rank = b->sq[7][5].rank = kBishop;
- b->sq[0][kQueenCol].rank = b->sq[7][kQueenCol].rank = kQueen;
- b->sq[0][kKingCol].rank = b->sq[7][kKingCol].rank = kKing;
- for (row=0; row<8; row++) {
- for (col=0; col<8; col++) {
- b->pieceNeverMoved[row][col] = true;
- }
- }
- b->lastMove.fromSquare.row = b->lastMove.fromSquare.col = 0xffff;
- b->lastMove.toSquare.row = b->lastMove.toSquare.col = 0xffff;
- }
-
- #if PRINT_PIECES
- static void PrintPieces(UInt32 numPieces, ChessPiece *piece, char *s)
- {
- int j;
- printf("%s %ld\n", s,numPieces);
- for (j=0; j<numPieces; j++) {
- printf("%c%c %c%c\n",
- gColor[piece[j].whichColor],gRank[piece[j].whichRank],
- gCol[piece[j].pieceLocation.col],gRow[piece[j].pieceLocation.row]);
- }
- }
- #else
- static void PrintPieces(UInt32 numPieces, ChessPiece *piece, char *s) {
- #pragma unused(numPieces)
- #pragma unused(piece)
- #pragma unused(s)
- };
- #endif
-
- #if PRINT_MOVES
- static void PrintMoves(UInt32 numMoves, ChessMove *move, char *s)
- {
- int j;
- printf("%s %ld\n",s,numMoves);
- for (j=0; j<numMoves; j++) {
- printf("%d %c%c%c%c%c",j,
- gCol[move[j].fromSquare.col],gRow[move[j].fromSquare.row],
- move[j].capture ? 'x' : '-',
- gCol[move[j].toSquare.col],gRow[move[j].toSquare.row]);
- if (move[j].capture) {
- printf(" %c%c\n",
- gCol[move[j].capturedSquare.col],gRow[move[j].capturedSquare.row]);
- } else {
- printf("\n");
- }
- }
- }
- #else
- static void PrintMoves(UInt32 numMoves, ChessMove *move, char *s) {
- #pragma unused(numMoves)
- #pragma unused(move)
- #pragma unused(s)
- };
- #endif
-
- #if PRINT_BOARD
- static void PrintBoard(Board *b)
- {
- int row,col;
- printf(" a b c d e f g h \n");
- for (row=7; row>=0; row--) {
- printf("%2d ",row+1);
- for (col=0; col<8; col++) {
- printf("%c%c ",gColor[b->sq[row][col].color], gRank[b->sq[row][col].rank]);
- }
- printf("\n");
- }
- printf(" %c%c%c%c%c\n\n",
- gCol[b->lastMove.fromSquare.col],gRow[b->lastMove.fromSquare.row],
- b->lastMove.capture ? 'x' : '-',
- gCol[b->lastMove.toSquare.col],gRow[b->lastMove.toSquare.row] );
- }
- #else
- static void PrintBoard(Board *b) {
- #pragma unused(b)
- };
- #endif
-
- static PieceColor OtherColor(PieceColor c)
- {
- return (PieceColor)(3 - (int)c); /* white is 1, black is 2 */
- }
-
- static Boolean FindKing(Board *b,PieceColor color, Square *kingSq)
- {
- int row,col;
- for (row=0; row<8; row++)
- for (col=0; col<8; col++) {
- if ( (b->sq[row][col].color == color) && (b->sq[row][col].rank==kKing)) {
- kingSq->row = row; kingSq->col = col; return true;
- }
- }
- return false;
- }
-
- static void MovePiece(Board *b, ChessMove *m, PieceColor colorToMove)
- {
- int fromRow = m->fromSquare.row;
- int fromCol = m->fromSquare.col;
- int toRow = m->toSquare.row;
- int toCol = m->toSquare.col;
- PieceColor ourColor = b->sq[fromRow][fromCol].color;
- int homeRow = (ourColor==kWhite) ? 0 : 7;
- if (colorToMove != ourColor) printf("** ERR moving wrong color piece\n");
- if (!m->capture) {
- if (b->sq[toRow][toCol].color != kEmpty) {
- printf(" ** bad move fromSq=(%d %d) toSq=(%d %d) our color=%d other color=%d\n",
- fromRow,fromCol,toRow,toCol,
- b->sq[fromRow][fromCol].color,b->sq[toRow][toCol].color);
- }
- } else { // debug test fails incorrectly for en passant
- // if (b->sq[toRow][toCol].color != OtherColor(b->sq[fromRow][fromCol].color)) {
- // printf(" ** bad capture fromSq=(%d %d) toSq=(%d %d) our color=%d other color=%d\n",
- // fromRow,fromCol,toRow,toCol,
- // b->sq[fromRow][fromCol].color,b->sq[toRow][toCol].color);
- // }
- /* includes en passant */
- b->sq[m->capturedSquare.row][m->capturedSquare.col].color = kEmpty;
- b->sq[m->capturedSquare.row][m->capturedSquare.col].rank = kNone;
- }
- /* check castle */
- if ( (b->sq[fromRow][fromCol].rank == kKing) && (fromRow==homeRow) && (fromCol==kKingCol) &&
- (b->sq[fromRow][fromCol].color==ourColor) ) {
- if ( (toCol==2) && (b->sq[fromRow][1].rank==kRook)) {
- b->sq[fromRow][3].color = b->sq[fromRow][0].color;
- b->sq[fromRow][3].rank = b->sq[fromRow][0].rank;
- b->sq[fromRow][0].color = kEmpty;
- b->sq[fromRow][0].rank = kNone;
- } else if ( (toCol==6) && (b->sq[fromRow][7].rank==kRook) ) {
- b->sq[fromRow][5].color = b->sq[fromRow][7].color;
- b->sq[fromRow][5].rank = b->sq[fromRow][7].rank;
- b->sq[fromRow][7].color = kEmpty;
- b->sq[fromRow][7].rank = kNone;
- }
- }
- /* check pawn promotion */
- if ( (b->sq[fromRow][fromCol].rank == kPawn) && (b->sq[fromRow][fromCol].color==ourColor) &&
- (toRow==7-homeRow) ) {
- /* promote in place, move code will update proper location */
- b->sq[toRow][toCol].rank = kQueen;
- }
- /* update board */
- b->sq[toRow][toCol].color = b->sq[fromRow][fromCol].color;
- b->sq[toRow][toCol].rank = b->sq[fromRow][fromCol].rank;
- b->sq[fromRow][fromCol].color = kEmpty;
- b->sq[fromRow][fromCol].rank = kNone;
- b->pieceNeverMoved[fromRow][fromCol] = false;
- b->pieceNeverMoved[toRow][toCol] = false;
- b->lastMove = *m;
- FindKing(b,ourColor,&b->kingSq);
- }
-
- static SInt16 gDeltaRow[8] = { 0, 1, 1, 1, 0, -1, -1, -1};
- static SInt16 gDeltaCol[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
- static SInt16 gKnightDeltaRow[8] = {1,2,2,1,-1,-2,-2,-1};
- static SInt16 gKnightDeltaCol[8] = {-2,-1,1,2,2,1,-1,-2};
-
- static Boolean LegalSquare(SInt16 row, SInt16 col) { /* note need for signed value */
- return ((row>=0) && (row<8) && (col>=0) && (col<8));
- }
-
- static Boolean LegalRelSquare(Board *b, SInt16 row, SInt16 col, int dir, int dist, Piece *sq)
- {
- Boolean result;
- row += gDeltaRow[dir]*dist;
- col += gDeltaCol[dir]*dist;
- result = LegalSquare(row, col);
- if (result) *sq = b->sq[row][col];
- return result;
- }
-
- static Boolean LegalKnightRelSquare(Board *b, SInt16 row, SInt16 col, int dir, Piece *sq)
- {
- Boolean result;
- row += gKnightDeltaRow[dir];
- col += gKnightDeltaCol[dir];
- result = LegalSquare(row,col);
- if (result) *sq = b->sq[row][col];
- return result;
- }
-
- static Boolean MovesDiagonally(PieceRank rank, UInt16 dist) {
- return ((rank==kQueen)||(rank==kBishop)||( (dist==1) && (rank==kKing) ) );
- }
-
- static Boolean MovesRectangularly(PieceRank rank, UInt16 dist) {
- return ((rank==kQueen)||(rank==kRook)||( (dist==1) && (rank==kKing) ) );
- }
-
- static Boolean SquareIsAttacked(Board *b, SInt16 row, SInt16 col)
- {
- Piece onSquare;
- PieceColor ourColor = b->sq[row][col].color;
- PieceColor opponentColor = OtherColor(ourColor);
- int dir,dist;
-
- for (dir=1; dir<8; dir+=2) { /* check diagonals */
- for (dist=1; dist<8; dist++) { /* check distance */
- if (!LegalRelSquare(b, row, col, dir, dist, &onSquare)) break;
- if (onSquare.color == kEmpty) break;
- if (onSquare.color == ourColor) break;
- if (onSquare.color == opponentColor) {
- if ( MovesDiagonally(onSquare.rank,dist) )
- return true;
- } else break;
- }
- }
-
- for (dir=0; dir<8; dir+=2) { /* check files */
- for (dist=1; dist<8; dist++) { /* check distance */
- if (!LegalRelSquare(b, row, col, dir, dist, &onSquare)) break;
- if (onSquare.color == kEmpty) break;
- if (onSquare.color == ourColor) break;
- if (onSquare.color == opponentColor) {
- if ( MovesRectangularly(onSquare.rank,dist) )
- return true;
- } else {
- break;
- }
- }
- }
-
- for (dir=0; dir<8; dir++) { /* check knights */
- if (!LegalKnightRelSquare(b, row, col, dir, &onSquare)) continue;
- if (onSquare.color == kEmpty) continue;
- if (onSquare.color == ourColor) continue;
- if ( (onSquare.color == opponentColor) && (onSquare.rank == kKnight) )
- return true;
- }
-
- /* check pawns */
- if (LegalRelSquare(b, row, col, (ourColor==kWhite) ? 1 : 8-1, 1, &onSquare))
- if ( (onSquare.color==opponentColor) && (onSquare.rank==kPawn))
- return true;
- if (LegalRelSquare(b, row, col, (ourColor==kWhite) ? 3 : 8-3, 1, &onSquare))
- if ( (onSquare.color==opponentColor) && (onSquare.rank==kPawn))
- return true;
- return false;
- }
-
- static void CreateMove(ChessMove *m, UInt16 row, UInt16 col, int dir, int dist, Piece *sq)
- {
- m->fromSquare.row = row;
- m->fromSquare.col = col;
- m->toSquare.row = row + gDeltaRow[dir]*dist;
- m->toSquare.col = col + gDeltaCol[dir]*dist;
- m->capture = false;
- if (sq->color != kEmpty) { /* pawns need to be handled separately */
- m->capture = true;
- m->capturedSquare = m->toSquare;
- }
- }
-
- static void CreateKnightMove(ChessMove *m, UInt16 row, UInt16 col, int dir, Piece *sq)
- {
- m->fromSquare.row = row;
- m->fromSquare.col = col;
- m->toSquare.row = row + gKnightDeltaRow[dir];
- m->toSquare.col = col + gKnightDeltaCol[dir];
- m->capture = false;
- if (sq->color != kEmpty) { /* pawns need to be handled separately */
- m->capture = true;
- m->capturedSquare = m->toSquare;
- }
- }
-
- static Boolean CheckMove(Board *origBoard, ChessMove **moves, SInt16 row, SInt16 col, int dir, int dist, Piece *onSquare,UInt32 *numMovesAdded)
- {
- ChessMove theMove;
- Board b = *origBoard;
- if (b.sq[row][col].rank == kKnight) {
- CreateKnightMove(&theMove,row,col,dir,onSquare);
- } else {
- CreateMove(&theMove,row,col,dir,dist,onSquare);
- }
- MovePiece(&b, &theMove, b.sq[row][col].color);
- if (SquareIsAttacked(&b, b.kingSq.row,b.kingSq.col)) {/* moves king into check or leaves king in check */
- return false;
- }
- **moves = theMove;
- (*moves)++;
- ++*numMovesAdded;
- return true;
- }
-
- static Boolean CheckEPMove(Board *origBoard, ChessMove **moves, SInt16 row, SInt16 col,
- SInt16 captureRow, SInt16 captureCol,int dir, Piece *onSquare,UInt32 *numMovesAdded)
- {
- ChessMove theMove;
- Board b = *origBoard;
- CreateMove(&theMove,row,col,dir,1,onSquare);
- theMove.capturedSquare.row = captureRow;
- theMove.capturedSquare.col = captureCol;
- theMove.capture = true;
- MovePiece(&b, &theMove,b.sq[row][col].color);
- if (SquareIsAttacked(&b, b.kingSq.row,b.kingSq.col)) {/* moves king into check or leaves king in check */
- return false;
- }
- **moves = theMove;
- (*moves)++;
- ++*numMovesAdded;
- return true;
- }
-
- static UInt32 CreateLegalPawnMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *origMoves)
- {
- PieceColor ourColor = origBoard->sq[row][col].color;
- PieceColor opponentColor = OtherColor(ourColor);
- UInt32 numMovesAdded = 0;
- Piece onSquare;
- int dir,dist,homeRow,advanceRowDir,enPassantRow;
- ChessMove *moves = origMoves;
-
- if (ourColor==kWhite) {
- dir = 2;
- enPassantRow = 4;
- advanceRowDir = 1;
- } else {
- dir = 8-2;
- enPassantRow = 7-4;
- advanceRowDir = -1;
- }
- dir = ourColor==kWhite ? 2 : 8-2; /* check moves ahead */
- homeRow = (ourColor==kWhite) ? 1 : 7-1; /* home row is 1 for white and 6 for black */
-
- /* check move one ahead */
- dist = 1;
- if ( (LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) &&
- (onSquare.color == kEmpty) ) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- }
-
- /* check move two ahead */
- dist = 2;
- if ( (origBoard->pieceNeverMoved[row][col]) &&
- (row == homeRow) &&
- (LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) /* set onSquare */ &&
- (onSquare.color == kEmpty) ){
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- }
-
- /* check capture right (including en passant) */
- dir = ourColor==kWhite ? 3 : 8-3;
- dist=1;
- if ( LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) {
- if (onSquare.color == opponentColor) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- } else {
- SInt16 epCol = col+gDeltaCol[dir];
- if ( (onSquare.color == kEmpty) &&
- (row==enPassantRow) &&
- (origBoard->sq[row][epCol].rank == kPawn) &&
- (origBoard->sq[row][epCol].color == opponentColor) &&
- (origBoard->lastMove.toSquare.row == enPassantRow) &&
- (origBoard->lastMove.fromSquare.row == enPassantRow+2*advanceRowDir) &&
- (origBoard->lastMove.fromSquare.col == col + gDeltaCol[dir]) &&
- (origBoard->lastMove.toSquare.col == col + gDeltaCol[dir]) ) {
- CheckEPMove(origBoard,&moves,row,col,row,epCol,dir,&onSquare, &numMovesAdded);
-
- // printf("** checking en passant (r,c)=(%d %d) ep=(%d %d)\n",
- // row,col,origBoard->lastMove.fromSquare.row,origBoard->lastMove.fromSquare.col);
- }
- }
- }
-
- /* check capture left (including en passant) */
- dir = ourColor==kWhite ? 1 : 8-1;
- dist=1;
- if ( LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) {
- if (onSquare.color == opponentColor) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- } else {
- SInt16 epCol = col+gDeltaCol[dir];
- if ( (onSquare.color == kEmpty) &&
- (row==enPassantRow) &&
- (origBoard->sq[row][epCol].rank == kPawn) &&
- (origBoard->sq[row][epCol].color == opponentColor) &&
- (origBoard->lastMove.toSquare.row == enPassantRow) &&
- (origBoard->lastMove.fromSquare.row == enPassantRow-2*advanceRowDir) &&
- (origBoard->lastMove.fromSquare.col == col + gDeltaCol[dir]) &&
- (origBoard->lastMove.toSquare.col == col + gDeltaCol[dir]) ) {
- CheckEPMove(origBoard,&moves,row,col,row,epCol,dir,&onSquare, &numMovesAdded);
- // printf("** checking en passant (r,c)=(%d %d) ep=(%d %d)\n",
- // row,col,origBoard->lastMove.fromSquare.row,origBoard->lastMove.fromSquare.col);
- }
- }
- }
-
- return moves-origMoves;
- }
-
- static UInt32 CreateLegalKnightMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves)
- {
- PieceColor ourColor = origBoard->sq[row][col].color;
- PieceColor opponentColor = OtherColor(ourColor);
- UInt32 numMovesAdded = 0;
- Piece onSquare;
- int dir,dist=0;
-
- for (dir=0; dir<8; dir++) {
- if (!LegalKnightRelSquare(origBoard, row, col, dir, &onSquare)) continue;
- if (onSquare.color == ourColor) continue;
- if ((onSquare.color == opponentColor) || (onSquare.color == kEmpty) ){
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- continue;
- }
- }
-
- return numMovesAdded;
- }
-
- static UInt32 CreateLegalBishopMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves)
- {
- PieceColor ourColor = origBoard->sq[row][col].color;
- PieceColor opponentColor = OtherColor(ourColor);
- UInt32 numMovesAdded = 0;
- Piece onSquare;
- int dir,dist;
-
- for (dir=1; dir<8; dir+=2) {
- for (dist=1; dist<8; dist++) { /* check distance */
- if (!LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) break;
- if (onSquare.color == ourColor) break;
- if (onSquare.color == opponentColor) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- break;
- } else if (onSquare.color == kEmpty) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- continue;
- }
- }
- }
-
- return numMovesAdded;
- }
-
- static UInt32 CreateLegalRookMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves)
- {
- PieceColor ourColor = origBoard->sq[row][col].color;
- PieceColor opponentColor = OtherColor(ourColor);
- UInt32 numMovesAdded = 0;
- Piece onSquare;
- int dir,dist;
-
- for (dir=0; dir<8; dir+=2) {
- for (dist=1; dist<8; dist++) { /* check distance */
- if (!LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) break;
- if (onSquare.color == ourColor) break;
- if (onSquare.color == opponentColor) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- break;
- } else if (onSquare.color == kEmpty) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- continue;
- }
- }
- }
-
- return numMovesAdded;
- }
-
- static UInt32 CreateLegalQueenMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves)
- {
- PieceColor ourColor = origBoard->sq[row][col].color;
- PieceColor opponentColor = OtherColor(ourColor);
- UInt32 numMovesAdded = 0;
- Piece onSquare;
- int dir,dist;
-
- for (dir=0; dir<8; dir++) {
- for (dist=1; dist<8; dist++) { /* check distance */
- if (!LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) break;
- if (onSquare.color == ourColor) break;
- if (onSquare.color == opponentColor) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- break;
- } else if (onSquare.color == kEmpty) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- continue;
- }
- }
- }
-
- return numMovesAdded;
- }
-
- static UInt32 CreateLegalKingMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves)
- {
- PieceColor ourColor = origBoard->sq[row][col].color;
- PieceColor opponentColor = OtherColor(ourColor);
- UInt32 numMovesAdded = 0;
- Piece onSquare;
- int dir,dist,homeRow;
-
- if (ourColor==kWhite) {
- homeRow = 0;
- } else {
- homeRow = 7;
- }
-
- for (dir=0; dir<8; dir++) {
- dist = 1;
- if (!LegalRelSquare(origBoard, row, col, dir, dist, &onSquare)) continue;
- if (onSquare.color == ourColor) continue;
- if ( (onSquare.color == opponentColor) || (onSquare.color == kEmpty) ) {
- CheckMove(origBoard,&moves,row,col,dir,dist,&onSquare, &numMovesAdded);
- continue;
- }
- }
- if ( (row==homeRow) && (col==kKingCol) &&
- origBoard->pieceNeverMoved[row][col] &&
- !SquareIsAttacked(origBoard, row, col)) {
- ChessMove theMove;
- if ( origBoard->pieceNeverMoved[row][0] &&
- !SquareIsAttacked(origBoard, row, 0) && !SquareIsAttacked(origBoard, row, 1) &&
- !SquareIsAttacked(origBoard, row, 2) && !SquareIsAttacked(origBoard, row, 3) &&
- origBoard->sq[row][1].color==kEmpty && origBoard->sq[row][2].color==kEmpty &&
- origBoard->sq[row][3].color==kEmpty ) {
- theMove.fromSquare.row = row; theMove.fromSquare.col = col;
- theMove.toSquare.row = row; theMove.toSquare.col = 1;
- theMove.capture = false;
- *moves = theMove;
- (moves)++;
- ++numMovesAdded;
- }
- if ( origBoard->pieceNeverMoved[row][7] &&
- !SquareIsAttacked(origBoard, row, 7) && !SquareIsAttacked(origBoard, row, 6) &&
- !SquareIsAttacked(origBoard, row, 5) &&
- origBoard->sq[row][6].color==kEmpty && origBoard->sq[row][5].color==kEmpty ) {
- theMove.fromSquare.row = row; theMove.fromSquare.col = col;
- theMove.toSquare.row = row; theMove.toSquare.col = 6;
- theMove.capture = false;
- *moves = theMove;
- (moves)++;
- ++numMovesAdded;
- }
- }
-
- return numMovesAdded;
- }
-
- static UInt32 CreateLegalMoves(Board *origBoard, SInt16 row, SInt16 col, ChessMove *moves)
- {
- PieceRank rank = origBoard->sq[row][col].rank;
- UInt32 numMovesAdded = 0;
- switch (rank) {
- case kPawn:
- numMovesAdded = CreateLegalPawnMoves(origBoard,row,col,moves);
- break;
- case kKnight:
- numMovesAdded = CreateLegalKnightMoves(origBoard,row,col,moves);
- break;
- case kBishop:
- numMovesAdded = CreateLegalBishopMoves(origBoard,row,col,moves);
- break;
- case kRook:
- numMovesAdded = CreateLegalRookMoves(origBoard,row,col,moves);
- break;
- case kQueen:
- numMovesAdded = CreateLegalQueenMoves(origBoard,row,col,moves);
- break;
- case kKing:
- numMovesAdded = CreateLegalKingMoves(origBoard,row,col,moves);
- break;
- default:
- printf("** piece rank err %d\n",rank);
- numMovesAdded = 0;
- break;
- }
- return numMovesAdded;
- }
-
- static UInt32 FindRemainingPieces(Board *b, ChessPiece *piece)
- {
- int row,col;
- UInt32 numPiecesRemaining = 0;
- for (row=0; row<8; row++)
- for (col=0; col<8; col++)
- if (b->sq[row][col].color != kEmpty) {
- piece->whichColor = b->sq[row][col].color;
- piece->whichRank = b->sq[row][col].rank;
- piece->pieceLocation.row = row;
- piece->pieceLocation.col = col;
- piece++;
- numPiecesRemaining++;
- }
- return numPiecesRemaining;
- }
-
- pascal void FindCorrectLegalChessMoves(
- UInt32 numPriorMoves,
- ChessMove priorMoves[],
- UInt32 *numPiecesRemaining,
- ChessPiece piecesRemaining[],
- UInt32 *numLegalMoves,
- ChessMove legalMoves[]
- ) {
- int i;
- SInt16 row,col;
- Board bd;
- UInt32 myNumLegalMoves = 0;
- UInt32 myNumPiecesRemaining = 0;
- PieceColor colorToMove = kWhite;
- InitBoard(&bd);
- PrintBoard(&bd);
- for (i=0; i<numPriorMoves; i++) {
- MovePiece(&bd,&priorMoves[i],colorToMove);
- PrintBoard(&bd);
- colorToMove = OtherColor(colorToMove);
- }
- myNumPiecesRemaining = FindRemainingPieces(&bd, piecesRemaining);
- for (row=0; row<8; row++)
- for (col=0; col<8; col++)
- if (bd.sq[row][col].color == colorToMove)
- myNumLegalMoves += CreateLegalMoves(&bd,row,col,legalMoves+myNumLegalMoves);
- *numPiecesRemaining= myNumPiecesRemaining;
- *numLegalMoves = myNumLegalMoves;
- }
-
- pascal OSErr CheckChess( const FSSpec* infile, const FSSpec* outfile, Boolean *correct )
- {
- OSErr err;
- Handle indata;
- int j;
- UInt32 numPriorMoves,numPiecesRemaining,numLegalMoves,numCorrectPiecesRemaining,numCorrectLegalMoves;
- ChessPiece *piecesRemaining,*correctPiecesRemaining;
- ChessMove *priorMoves,*correctPriorMoves,*legalMoves,*correctLegalMoves;
-
- printf( "Starting Chess\n" );
- *correct = TRUE;
-
- err = ProblemFileRead( infile, &indata );
- if ( err == noErr ) {
- err = ReadUInt32FromHandle( indata, &numPriorMoves );
-
- piecesRemaining = (ChessPiece *)NewPtr(kMaxPiecesRemaining*sizeof(ChessPiece));
- if (0==piecesRemaining) DebugStr("\p problem allocating piecesRemaining");
- legalMoves = (ChessMove *)NewPtr(kMaxMoves*sizeof(ChessMove));
- if (0==legalMoves) DebugStr("\p problem allocating legalMoves");
- priorMoves = (ChessMove *)NewPtrClear((1+numPriorMoves)*sizeof(ChessMove));
- if (0==priorMoves) DebugStr("\p problem allocating priorMoves");
-
- ReadMoves(indata, numPriorMoves, priorMoves);
-
- FindLegalChessMoves(numPriorMoves,priorMoves,&numPiecesRemaining,piecesRemaining,
- &numLegalMoves,legalMoves);
-
- /* sort pieces remaining and legal moves */
- FastQSort((void *)piecesRemaining,(long)numPiecesRemaining,(long)sizeof(ChessPiece),SortPiecesCmp);
- FastQSort((void *)legalMoves,(long)numLegalMoves,(long)sizeof(ChessMove),SortMovesCmp);
-
- PrintPieces(numPiecesRemaining, piecesRemaining,"Number of pieces remaining reported");
- PrintMoves(numLegalMoves, legalMoves,"Number of moves reported");
-
- correctPiecesRemaining = (ChessPiece *)NewPtr(kMaxPiecesRemaining*sizeof(ChessPiece));
- if (0==correctPiecesRemaining) DebugStr("\p problem allocating correctPiecesRemaining");
- correctLegalMoves = (ChessMove *)NewPtr(kMaxMoves*sizeof(ChessMove));
- if (0==correctLegalMoves) DebugStr("\p problem allocating correctLegalMoves");
- correctPriorMoves = (ChessMove *)NewPtrClear((1+numPriorMoves)*sizeof(ChessMove));
- if (0==correctPriorMoves) DebugStr("\p problem allocating correctPriorMoves");
- BlockMove(priorMoves,correctPriorMoves,numPriorMoves*sizeof(ChessMove));
-
- FindCorrectLegalChessMoves(numPriorMoves,correctPriorMoves,&numCorrectPiecesRemaining,correctPiecesRemaining,
- &numCorrectLegalMoves,correctLegalMoves);
-
- #if PRINT_CORRECT_RESULTS
- PrintPieces(numCorrectPiecesRemaining, correctPiecesRemaining,"Correct number of pieces remaining");
- PrintMoves(numCorrectLegalMoves, correctLegalMoves,"Correct number of moves");
- #endif
-
- /* sort pieces remaining and legal moves */
- FastQSort((void *)correctPiecesRemaining,(long)numCorrectPiecesRemaining,(long)sizeof(ChessPiece),SortPiecesCmp);
- FastQSort((void *)correctLegalMoves,(long)numCorrectLegalMoves,(long)sizeof(ChessMove),SortMovesCmp);
-
- if (numPiecesRemaining != numCorrectPiecesRemaining) {
- *correct = false;
- } else {
- for (j=0; j<numCorrectPiecesRemaining; j++) {
- if ( (piecesRemaining[j].whichColor != correctPiecesRemaining[j].whichColor) ||
- (piecesRemaining[j].whichRank != correctPiecesRemaining[j].whichRank) ||
- (piecesRemaining[j].pieceLocation.col != correctPiecesRemaining[j].pieceLocation.col) ||
- (piecesRemaining[j].pieceLocation.row != correctPiecesRemaining[j].pieceLocation.row) )
- *correct = false;
- }
- if (numLegalMoves != numCorrectLegalMoves) {
- *correct = false;
- } else {
- for (j=0; j<numCorrectLegalMoves; j++) {
- if ( (legalMoves[j].fromSquare.col != correctLegalMoves[j].fromSquare.col) ||
- (legalMoves[j].fromSquare.row != correctLegalMoves[j].fromSquare.row) ||
- (legalMoves[j].toSquare.col != correctLegalMoves[j].toSquare.col) ||
- (legalMoves[j].toSquare.row != correctLegalMoves[j].toSquare.row) ||
- (legalMoves[j].capture != correctLegalMoves[j].capture) ||
- (correctLegalMoves[j].capture &&
- ( (legalMoves[j].capturedSquare.col != correctLegalMoves[j].capturedSquare.col) ||
- (legalMoves[j].capturedSquare.row != correctLegalMoves[j].capturedSquare.row) )) )
- *correct = false;
- }
- }
- }
-
- if (correctPriorMoves) DisposePtr((Ptr)correctPriorMoves);
- if (correctLegalMoves) DisposePtr((Ptr)correctLegalMoves);
- if (correctPiecesRemaining) DisposePtr((Ptr)correctPiecesRemaining);
- if (priorMoves) DisposePtr((Ptr)priorMoves);
- if (legalMoves) DisposePtr((Ptr)legalMoves);
- if (piecesRemaining) DisposePtr((Ptr)piecesRemaining);
- }
- // printf("Done.\n");
- if (indata) DisposeHandle(indata);
-
- return noErr;
- }
-
-